package com.ydy.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.mysql.jdbc.Field;

import com.ydy.domain.Emp;
import com.ydy.domain.ScoreInfo;
import com.ydy.domain.Student;
//import com.ydy.service.AddrService;
import com.ydy.vo.CommonConstants;
import com.ydy.vo.JsonResult;
import com.ydy.vo.Studentvo;
import jdk.nashorn.internal.runtime.JSONFunctions;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.authc.Account;
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.swing.*;
import javax.xml.soap.Name;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@Slf4j
@RequiredArgsConstructor
public class StudentBizImpl implements StudentBiz {


    @Autowired
    private StudentService studentService;
    @Autowired
    private EmpService empService;

    private final StringRedisTemplate stringRedisTemplate;
    @Autowired
    private ScoreInfoService scoreInfoService;



    @Override
    public void insertStudent(Student student) {

    }

    @Override
    public void updateStudentByName(Student student) {
        if(student.getId() == null){
            throw new RuntimeException("id不能为空");
        }
        Student byId = studentService.getById(student.getId());
        if(byId!= null){
            byId.setName(student.getName());
            studentService.updateById(byId);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteById(Integer id) {
        studentService.removeById(id);
    }

    @Override
    public Studentvo getStudentvo(Integer id) {
      Student student = studentService .getById(id);
      if (student == null){
          throw new RuntimeException("用户不存在");
      }
      Studentvo studentvo = new Studentvo();
      studentvo.setId(student.getId());
      studentvo.setName(student.getName());

        Emp emp = empService.getOne(new LambdaQueryWrapper<Emp>().eq(Emp::getStuId,id).last("limit 1"));
        if (emp !=null){
            studentvo.setEmp(emp);
        }
        return studentvo;
    }

    @Override
@Transactional(rollbackFor =  Exception.class)
    public void addStudent(Studentvo studentvo) {
        Student student = new Student();
        student.setName(studentvo.getName());
        studentService.save(student);
        log.info("stu id:{}",student.getId());
        Emp emp = new Emp();
        emp.setId(studentvo.getId());
        emp.setName(studentvo.getName());
        emp.setGender(studentvo.getGender());
        emp.setSalary(studentvo.getSalary());
        emp.setDeptId(studentvo.getDeptId());
        emp.setJoinDate(studentvo.getJoinDate());
        emp.setStuId(student.getId());
        empService.save(emp);
        log.info("studentvo:{}新增成功",studentvo);


    }
  public static final String STUDENT_KEY ="student:";
    @Override
    public Studentvo getSrudentvowithRedis(String name) {
        String s = stringRedisTemplate.opsForValue().get(STUDENT_KEY + name);
        if (!StringUtils.isEmpty(s)){
            Studentvo studentvo = JSON.parseObject(s,Studentvo.class);
            return  studentvo;
        }
        Studentvo studentvo = this.getSrudentvowithAccount(name);
        stringRedisTemplate .opsForValue().set (STUDENT_KEY+name,JSON.toJSONString(studentvo),10, TimeUnit.SECONDS);
        try{
            Thread.sleep(1000);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        return studentvo;


    }

    @Override
    public boolean checkName(String name, String password) {
        Studentvo studentvoWithName = this.getSrudentvowithRedis(name);
        if (null == studentvoWithName){
            return  false;
        }
        if (studentvoWithName.getPassword().equals(password)){
            return  true;
        }
        return false;
    }

    @Override
    public Studentvo getSrudentvowithAccount(String name) {
        Studentvo studentvo=new Studentvo();
            Student one = studentService.getOne(new LambdaQueryWrapper<Student>().eq(Student::getName, name).last("limit 1"));
            if (one == null) {
                throw new RuntimeException("用户不存在");

            }
        studentvo.setName(one.getName());
        Student user=studentService.getById(one.getId());
        studentvo.setName(user.getName());
        studentvo.setId(user.getId());
        studentvo.setPassword(user.getPassword()) ;

            return studentvo;
        }


//    @Override
//    public Studentvo getSrudentvowithAccount(String name) {
//      Studentvo studentvo  = new Studentvo();
//      Emp one = empService.getOne(new LambdaQueryWrapper<Emp>().eq(Emp::getName,name).last("limit 1"));
//        if (one ==null){
//          throw new RuntimeException("用户不存在");
//        }
//        studentvo.setEmp(one);
//        Student student = studentService.getById(one.getStuId());
//        if (student ==null){
//            throw new RuntimeException("用户不存在");
//        }
//        studentvo.setId(student.getId());
//        studentvo.setName(student.getName());
//        studentvo.setPassword(student.getPassword());
//
//        Emp emp = empService.getOne(new LambdaQueryWrapper<Emp>().eq(Emp::getStuId,student.getId()).last("limit 1"));
//        if (emp !=null){
//            studentvo.setEmp(emp);
//        }
//        return studentvo;
//    }



    @Override
    public JsonResult addStudentInfo(Studentvo studentvo) {
        Student one = studentService.getOne(new LambdaQueryWrapper<Student>().eq(Student::getName, studentvo.getName()).last("limit 1"));
        if (one != null) {
            return JsonResult.fail("用户已存在");
        }
        Student oneByIp = studentService.getOne(new LambdaQueryWrapper<Student>().eq(Student::getIp, studentvo.getIp()).last("limit 1"));
        if (oneByIp != null) {
            return JsonResult.fail("用户ip已存在");
        }
        Student student = new Student();
        student.setName(studentvo.getName());
        student.setPassword(studentvo.getPassword());
        student.setCnName(studentvo.getCnName());
        student.setIp(studentvo.getIp());
        student.setCreateTime(new Date());
        studentService.save(student);//新增成功的student有id
        return JsonResult.suc("注册成功");
    }


    @Override
    public Studentvo checkAccount(String account, String password) {
        Studentvo studentvoWithAccount = this.getSrudentvowithAccount(account);
        if (null == studentvoWithAccount) {
            throw new RuntimeException("账号不存在");
        }
        if (studentvoWithAccount.getPassword().equals(password)) {
            return studentvoWithAccount;
        }else {
            throw new RuntimeException("密码错误");
        }
    }

    @Override
    public Studentvo getStudentInfo(ServletRequest request) {
        String token = ((ShiroHttpServletRequest) request).getHeader("token");
        if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isEmpty(token)) {
            throw new RuntimeException("token不能为空");
        }
        String s = stringRedisTemplate.opsForValue().get(CommonConstants.rangel_redis_key + CommonConstants.student_redis_key + token);
        if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isEmpty(s)) {
            throw new RuntimeException("token找不到用户");
        }
        Studentvo vo = JSON.parseObject(s,Studentvo.class);
        return vo;
    }

    @Override
    public JsonResult vote(ScoreInfo scoreInfo, HttpServletRequest request) {
        Studentvo studentInfo = this.getStudentInfo(request);//当前投票人信息
        if (null == studentInfo) {
            return JsonResult.fail("用户未登录");
        }
        if (null == scoreInfo.getScore()) {
            return JsonResult.fail("分数不能为空");
        }
        if (scoreInfo.getScore() < 0 || scoreInfo.getScore() > 100) {
            return JsonResult.fail("分数不能小于0 或 大于100");
        }
        if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isEmpty(scoreInfo.getTargetStuName())) {
            return JsonResult.fail("目标用户不能为空");
        }
        Studentvo userVoWithAccount = this.getSrudentvowithAccount(scoreInfo.getScoreStuName());
        if (null == userVoWithAccount) {
            return JsonResult.fail("目标用户不存在");
        }
        String remoteAddr = request.getRemoteAddr();
        if (!studentInfo.getIp().equals(remoteAddr)) {
            return JsonResult.fail("您投票ip与注册ip不一致");
        }
        //不校验是否给问一个目标重复投票
        scoreInfo.setScoreStuIp(remoteAddr);
        scoreInfo.setScoreStuName(studentInfo.getName());
        scoreInfo.setScoreStuId(studentInfo.getId());
        scoreInfo.setTargetStuId(userVoWithAccount.getId());
        scoreInfo.setCreateTime(new Date());
        scoreInfo.setId(null);
        scoreInfoService.save(scoreInfo);
        return JsonResult.suc("投票成功");
    }

    @Override
    public List<Student> findAllScoreInfo() {
        List<Student> list=studentService.list();
        for (Student student : list){
            Student oneScoreInfo =getOneScoreInfo(student);
            if (null != oneScoreInfo){
                student.setScore(oneScoreInfo.getScore());
                studentService.updateById(student);
            }
            student.setPassword(null);
        }
        return list;
    }

    @Override
    public String login(Studentvo studentvo) {
        return null;
    }
    public Student getOneScoreInfo(Student student) {
        if (null == student) {
            return null;
        }
        List<ScoreInfo> list = scoreInfoService.list(new LambdaQueryWrapper<ScoreInfo>()
                .eq(ScoreInfo::getTargetStuId, student.getId())
                .orderByDesc(ScoreInfo::getCreateTime)//根据投票时间排序
                .groupBy(ScoreInfo::getScoreStuId));//去重，根据投票人id去重，达到效果
        if (CollectionUtils.isEmpty(list) || list.size() <= 2) {
            student.setScore(0);
            return student;
        }
        //投票数>2，去掉最高分，去掉最低分
        int size = list.size();//总票数
        int totalScore = list.stream().mapToInt(ScoreInfo::getScore).sum();
        List<Integer> scoreList = list.stream().map(ScoreInfo::getScore).collect(Collectors.toList());
        Integer minScore = findMinScore(scoreList);
        Integer maxScore = findMaxScore(scoreList);
        totalScore = totalScore - minScore - maxScore;
        int score = totalScore / (size - 2);
        student.setScore(score);
        return student;
    }
    private static Integer findMaxScore(List<Integer> list) {
        return list.stream().reduce(list.get(0),Integer::max);
    }
    private static Integer findMinScore(List<Integer> list) {
        return list.stream().reduce(list.get(0),Integer::min);
    }

}
